import errno
import logging
import os
import sys
from datetime import datetime
from typing import Any

import yaml

LOGGER = logging.getLogger(__name__)


class Config:
    def __init__(self):
        self._config = {}
        self._initilized = False
        self._args = None

    def init(self, args):
        self._args = args
        fullpath = args.yaml
        try:
            with open(fullpath, 'r') as file_:
                self._config = yaml.safe_load(file_)
        except (IOError, OSError) as exception:
            # *** IO exception:
            LOGGER.critical("Failed to open config file %s, "
                            "error=%s", fullpath, exception)
            sys.exit("Exiting config module. Please create config file")
        except yaml.YAMLError as exception:
            # *** YAML exception:
            if hasattr(exception, 'problem_mark'):
                mark = exception.problem_mark
                LOGGER.critical("Failed to open config file %s, "
                                "error=%s on line=%s character=%s. Exiting",
                                fullpath, exception, mark.line+1, mark.column+1)
            else:
                LOGGER.critical("Failed to open config file=%s, "
                                "error=%s. Exiting", fullpath, exception)
            sys.exit("Exiting config module. Please fix config file")

        output_base_dir = os.path.join(os.path.abspath(
            self._config['output_base_dir']), datetime.now().strftime('%Y%m%d%H%M'))

        self._config.update({
            'output_dir_fullname': output_base_dir,
            'packet_dir_fullname': os.path.join(output_base_dir, "capturing"),
            'flow_info_fullname': os.path.join(output_base_dir, "flow_info.csv"),
            'url_info_fullname': os.path.join(output_base_dir, "url_info.csv"),
            'dst_ip_info_fullname': os.path.join(output_base_dir, "dst_ip_info.json"),
        })

        try:
            os.makedirs(self._config['output_dir_fullname'])
            if self._args.capture:
                os.mkdir(self._config['packet_dir_fullname'])
        except OSError as e:
            if e.errno != errno.EEXIST:
                LOGGER.critical(
                    "Failed to create output folder with error %s", e)
                sys.exit("System error occured when creating folder")

        LOGGER.info("Result will be saved to directory '%s'",
                    output_base_dir)
        self._initilized = True

    def __getattribute__(self, __name: str):
        if __name.startswith('_') or __name == "init":
            return object.__getattribute__(self, __name)

        if not self._initilized:
            LOGGER.critical("Config object not initilized.")
            sys.exit("Config object not initilized")

        if hasattr(self._args, __name):
            return getattr(self._args, __name)

        __val = self._config.get(__name)
        if __val is None:
            LOGGER.warning("Attribute %s not found in config", __name)

        return __val

    def __setattr__(self, __name: str, __value: Any):
        if __name.startswith('_'):
            object.__setattr__(self, __name, __value)

        self._config.__setitem__(__name, __value)


config = Config()
